Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 2 |
|
33.33% |
10 / 30 |
CRAP | |
88.93% |
241 / 271 |
| SWIFT_TestCase | |
0.00% |
0 / 1 |
|
66.67% |
8 / 12 |
56 | |
95.56% |
237 / 248 |
| setNextRecordLimit | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
| setNextRecordNoLimit | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
| setNextRecordType | |
100.00% |
1 / 1 |
3 | |
100.00% |
4 / 4 |
|||
| setUp | |
100.00% |
1 / 1 |
1 | |
100.00% |
6 / 6 |
|||
| tearDown | |
100.00% |
1 / 1 |
5 | |
100.00% |
8 / 8 |
|||
| mockProperty | |
0.00% |
0 / 1 |
2.01 | |
85.71% |
6 / 7 |
|||
| getMethod | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
| assertClassNotLoaded | |
0.00% |
0 / 1 |
2.09 | |
71.43% |
5 / 7 |
|||
| assertInvalidData | |
0.00% |
0 / 1 |
1.02 | |
75.00% |
3 / 4 |
|||
| getMockServices | |
0.00% |
0 / 1 |
31 | |
95.04% |
134 / 141 |
|||
| getMockObject | |
100.00% |
1 / 1 |
6 | |
100.00% |
59 / 59 |
|||
| setExpectedException | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| LoaderMock | |
0.00% |
0 / 1 |
|
11.11% |
2 / 18 |
269.61 | |
17.39% |
4 / 23 |
| __construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| __destruct | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| Library | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| Manage | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| Method | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| Index | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| Insert | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| Edit | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| View | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| Model | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| Redirect | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| InsertTicket | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| NewTicket | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| Search | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| NewTicketForm | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| RenderForm | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
| CheckForValidAttachments | |
0.00% |
0 / 1 |
20.00 | |
0.00% |
0 / 3 |
|||
| Controller | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 2 |
|||
| <?php | |
| /** | |
| * ############################################### | |
| * | |
| * SWIFT Framework | |
| * _______________________________________________ | |
| * | |
| * @author Varun Shoor | |
| * | |
| * @package SWIFT | |
| * @copyright Copyright (c) 2001-2012, Kayako | |
| * @license http://www.kayako.com/license | |
| * @link http://www.kayako.com | |
| * | |
| * ############################################### | |
| */ | |
| use Base\Library\Notification\SWIFT_NotificationManager; | |
| use Base\Models\User\SWIFT_User; | |
| /** | |
| * The SWIFT Test Case Class | |
| * | |
| * @author Varun Shoor | |
| */ | |
| abstract class SWIFT_TestCase extends \PHPUnit\Framework\TestCase | |
| { | |
| /** @var array stores a list of mocked services */ | |
| protected $mockServices = null; | |
| // Database NextRecord handling stuff | |
| const NEXT_RECORD_CUSTOM_LIMIT = 1; | |
| const NEXT_RECORD_NO_LIMIT = 2; | |
| const NEXT_RECORD_QUERY_RESET = 3; | |
| const NEXT_RECORD_RETURN_CALLBACK = 4; | |
| public static $nextRecordCount = 0; | |
| public static $nextRecordLimit = 1; | |
| public static $nextRecordType = self::NEXT_RECORD_CUSTOM_LIMIT; | |
| public static $databaseCallback = []; | |
| protected function setNextRecordLimit($_nextRecordLimit) | |
| { | |
| if (static::$nextRecordType === self::NEXT_RECORD_CUSTOM_LIMIT) { | |
| static::$nextRecordLimit = $_nextRecordLimit; | |
| } | |
| } | |
| protected function setNextRecordNoLimit() | |
| { | |
| static::$nextRecordCount = 0; | |
| static::$nextRecordLimit = 1; | |
| static::$nextRecordType = self::NEXT_RECORD_NO_LIMIT; | |
| } | |
| protected function setNextRecordType($_nextRecordType) | |
| { | |
| if ($_nextRecordType >= self::NEXT_RECORD_CUSTOM_LIMIT && | |
| $_nextRecordType <= self::NEXT_RECORD_RETURN_CALLBACK) { | |
| static::$nextRecordType = $_nextRecordType; | |
| } | |
| } | |
| protected function setUp() | |
| { | |
| unset($_POST, $_REQUEST, $_FILES); | |
| static::$nextRecordCount = 0; | |
| static::$nextRecordLimit = 1; | |
| static::$nextRecordType = self::NEXT_RECORD_CUSTOM_LIMIT; | |
| static::$databaseCallback = []; | |
| } | |
| protected function tearDown() | |
| { | |
| // speed things up by deleting objects in memory | |
| $refl = new ReflectionObject($this); | |
| foreach ($refl->getProperties() as $prop) { | |
| if (!$prop->isStatic() && | |
| (0 !== strpos($prop->getDeclaringClass()->getName(), 'PHPUnit\\') || | |
| 0 !== strpos($prop->getDeclaringClass()->getName(), 'PHPUnit_'))) { | |
| $prop->setAccessible(true); | |
| $prop->setValue($this, null); | |
| } | |
| } | |
| } | |
| /** | |
| * @param object $object The object whose property is to be mocked | |
| * @param string $propertyName The property name | |
| * @param mixed $value The property value | |
| */ | |
| public function mockProperty($object, $propertyName, $value) | |
| { | |
| try { | |
| $reflectionClass = new \ReflectionClass($object); | |
| $property = $reflectionClass->getProperty($propertyName); | |
| $property->setAccessible(true); | |
| $property->setValue($object, $value); | |
| $property->setAccessible(false); | |
| } catch (ReflectionException $e) { | |
| } | |
| } | |
| /** | |
| * Gets a Reflection method and sets it accessible | |
| * | |
| * @param string $className | |
| * @param string $methodName | |
| * | |
| * @return ReflectionMethod | |
| * @throws ReflectionException | |
| */ | |
| protected function getMethod($className, $methodName) | |
| { | |
| $method = new \ReflectionMethod($className, $methodName); | |
| $method->setAccessible(true); | |
| return $method; | |
| } | |
| /** | |
| * Helper method to assert if a class not loaded exception is thrown | |
| * | |
| * @param object $obj Object on which to call $methodName | |
| * @param string $methodName Name of the method to call | |
| * @param mixed $arg,... unlimited OPTIONAL number of arguments to pass to method | |
| */ | |
| protected function assertClassNotLoaded($obj, $methodName, $arg = null) | |
| { | |
| if (!method_exists($obj, 'SetIsClassLoaded')) { | |
| return; | |
| } | |
| $args = func_get_args(); | |
| $obj->SetIsClassLoaded(false); | |
| $this->setExpectedException(\SWIFT_Exception::class); | |
| call_user_func_array([$obj, $methodName], array_splice($args, 2)); | |
| } | |
| /** | |
| * Helper method to assert if invalid data exception is thrown | |
| * | |
| * @param object $obj Object on which to call $methodName | |
| * @param string $methodName Name of the method to call | |
| * @param mixed $arg,... unlimited OPTIONAL number of arguments to pass to method | |
| */ | |
| protected function assertInvalidData($obj, $methodName, $arg = null) | |
| { | |
| $args = func_get_args(); | |
| $this->setExpectedException('SWIFT_Exception', SWIFT_INVALIDDATA); | |
| call_user_func_array([$obj, $methodName], array_splice($args, 2)); | |
| } | |
| /** | |
| * Generates and stores a list of commonly used services | |
| * | |
| * @return array | |
| */ | |
| protected function getMockServices() | |
| { | |
| if ($this->mockServices !== null) { | |
| return $this->mockServices; | |
| } | |
| $mockDb = $this->getMockBuilder(SWIFT_Database::class) | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $mockDb->method('AutoExecute')->willReturn(true); | |
| $mockDb->method('Insert_ID')->willReturnCallback(function () { | |
| if (isset(static::$databaseCallback['Insert_ID'])) { | |
| return call_user_func(static::$databaseCallback['Insert_ID']); | |
| } | |
| return 1; | |
| }); | |
| $mockDb->method('QueryLimit')->willReturnCallback(function ($x) { | |
| if (static::$nextRecordType === static::NEXT_RECORD_QUERY_RESET) { | |
| static::$nextRecordCount = 0; | |
| } | |
| if (isset(static::$databaseCallback['QueryLimit'])) { | |
| call_user_func(static::$databaseCallback['QueryLimit'], $x); | |
| } | |
| return true; | |
| }); | |
| $mockDb->method('Query')->willReturnCallback(function ($x) { | |
| if (false !== strpos($x, 'SELECT customfieldid, fieldtype, customfieldgroupid from')) { | |
| static::$databaseCallback['stop'] = true; | |
| } | |
| if (static::$nextRecordType === static::NEXT_RECORD_QUERY_RESET) { | |
| static::$nextRecordCount = 0; | |
| } | |
| if (isset(static::$databaseCallback['Query'])) { | |
| call_user_func(static::$databaseCallback['Query'], $x); | |
| } | |
| }); | |
| $mockDb->method('QueryFetchAll')->willReturn([]); | |
| $mockDb->method('NextRecord')->willReturnCallback(function () { | |
| static::$nextRecordCount++; | |
| if (isset(static::$databaseCallback['stop'])) { | |
| unset(static::$databaseCallback['stop']); | |
| return false; | |
| } | |
| if (isset(static::$databaseCallback['NextRecord'])) { | |
| $ret = call_user_func(static::$databaseCallback['NextRecord']); | |
| if (static::$nextRecordType === static::NEXT_RECORD_RETURN_CALLBACK) { | |
| return $ret; | |
| } | |
| } | |
| if (static::$nextRecordType === static::NEXT_RECORD_CUSTOM_LIMIT) { | |
| return static::$nextRecordCount <= static::$nextRecordLimit; | |
| } | |
| if (static::$nextRecordType === static::NEXT_RECORD_NO_LIMIT || | |
| static::$nextRecordType === static::NEXT_RECORD_QUERY_RESET) { | |
| return static::$nextRecordCount % 2; | |
| } | |
| return false; | |
| }); | |
| $settings = $this->getMockBuilder('SWIFT_Settings') | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $settings->method('Get')->willReturnCallback(function ($x) { | |
| if (isset(static::$databaseCallback['SettingsGet'])) { | |
| return call_user_func(static::$databaseCallback['SettingsGet'], $x); | |
| } | |
| if ($x === 't_eticketid') { | |
| return 'seq'; | |
| } | |
| if ($x === 'tb_maxwordlength') { | |
| return '100'; | |
| } | |
| if ($x === 'security_captchatype') { | |
| return 'recaptcha'; | |
| } | |
| if (in_array($x, [ | |
| 'user_dispatchregemail', | |
| 't_slaresets', | |
| 'cpu_enablesmtp', | |
| ], true)) { | |
| // don't send welcome email | |
| // don't run clearOverdue on shutdown | |
| return '0'; | |
| } | |
| if (in_array($x, [ | |
| 'cpu_enablemailqueue', | |
| ], true)) { | |
| return 1; | |
| } | |
| if (false !== strpos($x, 'mail')) { | |
| return 'me@mail.com'; | |
| } | |
| if (isset(static::$databaseCallback['SettingsGet'])) { | |
| return call_user_func(static::$databaseCallback['SettingsGet'], $x); | |
| } | |
| return '1'; | |
| }); | |
| $mockCache = $this->getMockBuilder('SWIFT_CacheStore') | |
| ->disableOriginalConstructor() | |
| ->disableProxyingToOriginalMethods() | |
| ->getMock(); | |
| $mockCache->method('Get')->willReturnCallback(function ($x) { | |
| if (isset(static::$databaseCallback['CacheGet'])) { | |
| return call_user_func(static::$databaseCallback['CacheGet'], $x); | |
| } | |
| return [1 => [1 => [1]]]; | |
| }); | |
| $mockLang = $this->getMockBuilder('SWIFT_LanguageEngine') | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $mockLang->method('GetLinked')->willReturnCallback(function ($x) { | |
| if (isset(static::$databaseCallback['GetLinked'])) { | |
| return call_user_func(static::$databaseCallback['GetLinked'], $x); | |
| } | |
| return 1; | |
| }); | |
| $mockLang->method('Get')->willReturnCallback(function ($x) { | |
| if ($x === 'charset') { | |
| return 'UTF-8'; | |
| } | |
| if (false !== strpos($x, 'log')) { | |
| return '%s '; | |
| } | |
| return $x; | |
| }); | |
| $mgr = $this->getMockBuilder(SWIFT_NotificationManager::class) | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $mockUser = $this->getMockBuilder(SWIFT_User::class) | |
| ->disableOriginalConstructor() | |
| ->disableProxyingToOriginalMethods() | |
| ->setMethods(['GetIsClassLoaded', 'GetUserID', 'GetEmailList', 'GetProperty', 'Get', '__destruct']) | |
| ->getMock(); | |
| $this->mockProperty($mockUser, 'NotificationManager', $mgr); | |
| $mockUser->method('__destruct')->willReturn(true); | |
| $mockUser->method('GetIsClassLoaded')->willReturn(true); | |
| $mockUser->method('GetUserID')->willReturn(1); | |
| $mockUser->method('GetEmailList')->willReturn(['me@mail.com']); | |
| $mockUser->method('GetProperty')->willReturnArgument(0); | |
| $mockUser->method('Get')->willReturnCallback(function ($x) { | |
| if (isset(static::$databaseCallback['UserGet'])) { | |
| return call_user_func(static::$databaseCallback['UserGet'], $x); | |
| } | |
| if (substr($x, -2) === 'id') { | |
| return 1; | |
| } | |
| return $x; | |
| }); | |
| $mockStaff = $this->getMockBuilder('Base\Models\Staff\SWIFT_Staff') | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $mockStaff->method('GetPermission')->willReturnOnConsecutiveCalls('1', '0'); | |
| $mockStaff->method('GetIsClassLoaded')->willReturn(true); | |
| $mockStaff->method('GetStaffID')->willReturn(1); | |
| $mockStaff->method('GetProperty')->willReturnCallback(function ($x) { | |
| if (strtolower(substr($x, -2)) === 'id') { | |
| return '1'; | |
| } | |
| return $x; | |
| }); | |
| $mockSession = $this->getMockBuilder('SWIFT_Session') | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $mockSession->method('GetSessionID')->willReturn(1); | |
| $mockSession->method('GetIsClassLoaded')->willReturn(true); | |
| $mockSession->method('GetProperty')->willReturnCallback(function ($x) { | |
| if (strtolower(substr($x, -2)) === 'id') { | |
| return '1'; | |
| } | |
| if (false !== strpos($x, 'mail')) { | |
| return 'me@mail.com'; | |
| } | |
| return $x; | |
| }); | |
| $this->mockProperty(\SWIFT::GetInstance(), 'Load', new LoaderMock()); | |
| $this->mockProperty(\SWIFT::GetInstance(), 'Staff', $mockStaff); | |
| $this->mockProperty(\SWIFT::GetInstance(), 'User', $mockUser); | |
| $this->mockProperty(\SWIFT::GetInstance(), 'Session', $mockSession); | |
| $this->mockProperty(\SWIFT::GetInstance(), 'Database', $mockDb); | |
| $this->mockProperty(\SWIFT::GetInstance(), 'Cache', $mockCache); | |
| $this->mockProperty(\SWIFT::GetInstance(), 'Settings', $settings); | |
| $this->mockProperty(\SWIFT::GetInstance(), 'Language', $mockLang); | |
| return $this->mockServices = [ | |
| 'Staff' => $mockStaff, | |
| 'Session' => $mockSession, | |
| 'Database' => $mockDb, | |
| 'Cache' => $mockCache, | |
| 'Settings' => $settings, | |
| 'Language' => $mockLang, | |
| ]; | |
| } | |
| /** | |
| * This method creates a new instance of a class and assigns a set of mocked | |
| * services as properties | |
| * | |
| * @param string $objectMock The name of the class to create an instance from | |
| * @param array $_services A list of services to mock | |
| * @return mixed | |
| */ | |
| protected function getMockObject($objectMock, array $_services = []) | |
| { | |
| $this->getMockServices(); | |
| $services = []; | |
| if (is_subclass_of($objectMock, 'SWIFT_Controller') || | |
| is_subclass_of($objectMock, 'SWIFT_View')) { | |
| $mockView = $this->getMockBuilder('SWIFT_View') | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $mockInt = $this->getMockBuilder('Base\Library\UserInterface\SWIFT_UserInterfaceControlPanel') | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $mockGrid = $this->getMockBuilder('Base\Library\UserInterface\SWIFT_UserInterfaceGrid') | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $mockGrid->method('GetSearchQueryString')->willReturn('query'); | |
| $mockGrid->method('GetMode')->willReturn(2); | |
| if (is_subclass_of($objectMock, 'SWIFT_View')) { | |
| $mockTab = $this->getMockBuilder('Base\Library\UserInterface\SWIFT_UserInterfaceTab') | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $mockTb = $this->getMockBuilder('Base\Library\UserInterface\SWIFT_UserInterfaceToolbar') | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $this->mockProperty($mockInt, 'Toolbar', $mockTb); | |
| $this->mockProperty($mockTab, 'Toolbar', $mockTb); | |
| $mockInt->method('AddTab')->willReturn($mockTab); | |
| $mockInt->method('GetIsClassLoaded')->willReturn(true); | |
| $this->mockProperty($mockTab, 'UserInterface', $mockInt); | |
| } | |
| $mockTpl = $this->getMockBuilder('SWIFT_TemplateEngine') | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $this->mockProperty(\SWIFT::GetInstance(), 'UserInterface', $mockInt); | |
| $services['Template'] = $mockTpl; | |
| $services['UserInterface'] = $mockInt; | |
| $services['UserInterfaceGrid'] = $mockGrid; | |
| $services['View'] = $mockView; | |
| } | |
| if (is_subclass_of($objectMock, 'Controller_api') || | |
| is_subclass_of($objectMock, 'Controller_staffapi')) { | |
| $mgr = $this->getMockBuilder('SWIFT_RESTManager') | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $mgr->method('Authenticate') | |
| ->willReturn(true); | |
| $svr = $this->getMockBuilder('SWIFT_RESTServer') | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $svr->method('GetVariableContainer') | |
| ->willReturn(['salt' => '1']); | |
| $xml = $this->getMockBuilder('SWIFT_XML') | |
| ->disableOriginalConstructor() | |
| ->getMock(); | |
| $services['XML'] = $xml; | |
| $services['RESTManager'] = $mgr; | |
| $services['RESTServer'] = $svr; | |
| } | |
| return new $objectMock(array_merge([ | |
| 'Cache' => $this->mockServices['Cache'], | |
| 'Language' => $this->mockServices['Language'], | |
| 'Settings' => $this->mockServices['Settings'], | |
| 'Database' => $this->mockServices['Database'], | |
| ], $services, $_services)); | |
| } | |
| /** | |
| * Wrapper to make it easier to migrate to PHPUnit 6 | |
| * | |
| * @author Douglas Yau <douglas.yau@crossover.com> | |
| * @param mixed $class type of exception to expect | |
| * @param null $message not used, kept for compatibility | |
| * @param null $code | |
| */ | |
| public function setExpectedException($class, $message = null, $code = null) | |
| { | |
| $this->expectException($class); | |
| } | |
| } | |
| class LoaderMock | |
| { | |
| public $Load; | |
| protected $obj; | |
| /** | |
| * LoaderMock constructor. | |
| * @param Object|null $obj loader class | |
| */ | |
| public function __construct($obj = null) | |
| { | |
| $this->obj = $obj; | |
| } | |
| public function __destruct() | |
| { | |
| $this->obj = null; | |
| } | |
| public function Library($_libraryName, $_arguments = array(), $_initiateInstance = true, $_customAppName = false, $_appName = '') | |
| { | |
| return $_libraryName; | |
| } | |
| public function Manage() | |
| { | |
| return true; | |
| } | |
| public function Method($_methodName = '') | |
| { | |
| return true; | |
| } | |
| public function Index() | |
| { | |
| return true; | |
| } | |
| public function Insert() | |
| { | |
| return true; | |
| } | |
| public function Edit() | |
| { | |
| return true; | |
| } | |
| public function View($_viewName = '') | |
| { | |
| return true; | |
| } | |
| public function Model($_modelName = '', $_arguments = array(), $_initiateInstance = true, $_customAppName = false, $appName = '') | |
| { | |
| return true; | |
| } | |
| public function Redirect() | |
| { | |
| return true; | |
| } | |
| public function InsertTicket() | |
| { | |
| return true; | |
| } | |
| public function NewTicket() | |
| { | |
| return true; | |
| } | |
| public function Search() | |
| { | |
| return true; | |
| } | |
| public function NewTicketForm() | |
| { | |
| return true; | |
| } | |
| public function RenderForm() | |
| { | |
| return true; | |
| } | |
| /** | |
| * @param int $_hasAttachments | |
| * @return array | |
| */ | |
| public function CheckForValidAttachments($_hasAttachments) | |
| { | |
| if ($this->obj !== null && method_exists($this->obj, 'CheckForValidAttachments')) { | |
| return $this->obj->CheckForValidAttachments($_hasAttachments); | |
| } | |
| return $this->obj->_getAttachmentsReturnValue ?: [false, ['error']]; | |
| } | |
| public function Controller($_controllerName = '', $_customApp = '') | |
| { | |
| $this->Load = $this; | |
| return $this; | |
| } | |
| } |